#	 Copyright 2012, 2012 Noel Warren

#    This file is part of MiniVistii.
#    MiniVistii is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    MiniVistii is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Lesser General Public License for more details.

#    You should have received a copy of the GNU Lesser General Public License
#    along with MiniVistii.  If not, see <http://www.gnu.org/licenses/>.


def buildWorkpiece
    entities = Sketchup::active_model.active_entities
    definitions = Sketchup::active_model.definitions
    selection = Sketchup::active_model.selection
    bb = Geom::BoundingBox.new
	selection.each{|entity| bb.add entity.bounds}
	name = definitions.unique_name("Workpiece")
	input = UI.inputbox ["Name", "X", "Y", "Z"],
    					[name, bb.width, bb.height, bb.depth],
    					"Workpiece"
    if input
	    name = input[0]
	    x = input[1]
	    y = input[2]
	    z = input[3]
       	design = entities.add_group(selection.to_a)
    	tempGroup = entities.add_group([design])
    	stock = tempGroup.entities.add_group
    	stock.entities.add_edges [[0,0,0],[x,y,z]]
    	stock.visible = false 	
    	workpiece = tempGroup.to_component
    	workpiece.definition.name = name
		bundle = Bundle.open(workpiece)
		bundle["type"] = "workpiece"
		bundle.save
    	bundle = Bundle.open(design)
		bundle["type"] = "design"
		bundle.save
		bundle = Bundle.open(stock)
		bundle["type"] = "stock"
		bundle.save
	end
end

class DefineToolpathTool
	def activate
		@ip = Sketchup::InputPoint.new
	    @iptemp = Sketchup::InputPoint.new
	    @vertices = []
	    @edges = []
	    @prevedge = nil
	    @availableVertices = Sketchup::active_model.active_entities.collect{|ent| ent.vertices if (ent.is_a? Sketchup::Edge)}.flatten.uniq
	end
	
	def onMouseMove(flags, x, y, view)
	    @iptemp.pick view, x, y
	    if @iptemp.valid?
	        changed = @iptemp != @ip
	        @ip.copy! @iptemp
	        view.invalidate if changed
	    end
	end
	
	def onLButtonDown(flags, x, y, view)
		finished = false
	    if @ip.vertex && @availableVertices.include?(@ip.vertex)
	    	@vertices.push vertex = @ip.vertex
	    	if @vertices.length != 1
	    		@edges.push edge = vertex.common_edge(@vertices[-2])
	    		options = vertex.edges.delete_if{|edge| @edges.include? edge}
	    		while options.length >= 1
	    			@vertices.push vertex = options[0].other_vertex(vertex)
	    			@edges.push edge = options[0]
	    			options = vertex.edges.delete_if{|edge| @edges.include? edge}
	    		end
	    		finished = true
	    	end
	    end
	    if finished
	    	tools = CNC.tools
	    	compensation = ["0: None",
	    				  "R: Right",
	    				  "L: Left"]
	    	execution = [#"0: Reprecussion (Other workpieces)",
	    				 "1: Normal",
	    				 "2: Underneath"]
	    	prompts = ["Tool","Compensation","Execution"]
	    	defaults = [tools[0],compensation[0],execution[0]]
	    	list = [tools.join("|"),compensation.join("|"),execution.join("|")]
	    	if !CNC.hasToolChanger?
	    		prompts.delete_at(0)
	    		defaults.delete_at(0)
	    		list.delete_at(0)
	    	end
	    	input = UI.inputbox(prompts, defaults, list, "Toolpath")
	    	input.insert(0,nil) if !CNC.hasToolChanger?
			if input
				edges = @vertices.collect{|vertex| vertex.edges}.flatten.uniq
				if input[2][0,1] == "2"
					Sketchup.active_model.active_entities.transform_entities Geom::Transformation.scaling(1, 1, -1), edges
					group = Sketchup::active_model.active_entities.add_group edges
					group.transform! Geom::Transformation.scaling(1, 1, -1)
				else  
					group = Sketchup::active_model.active_entities.add_group edges
				end 
				bundle = Bundle.open(group)
				bundle["type"] = "toolpath"
				bundle["tool"] = input[0] if CNC.hasToolChanger?
				bundle["correction"] = input[1][0,1]
				if input[2][0,1] == "0"
					bundle["execution"] = "reprecussion"
				else 
					bundle["execution"] = "normal"
				end
				bundle.save
				group.entities.each{|entity| entity.vertices.each{|vertex| vertex.delete_attribute "minivistii"} if entity.typename == "Edge"}
				@vertices.each_index{|index|  
					bundle = Bundle.open(@vertices[index])
					if bundle["indices"]
						bundle["indices"].push index
					else
						bundle["indices"] = [index]
					end
					bundle.save
				}
		    end
	    	Sketchup::active_model.selection.clear
	    	Sketchup::active_model.selection.add group if group 
			Sketchup::active_model.select_tool nil
		end
	end
	
	def draw(view)
		if @ip.vertex
			if @availableVertices.include? @ip.vertex
				@ip.draw(view)
			end
		end
	end
end

class DefineHoleTool
	def activate
		@ip = Sketchup::InputPoint.new
	    @iptemp = Sketchup::InputPoint.new
	    @point = nil
	    @diameter = 5
	end
	
	def onMouseMove(flags, x, y, view)
	    @iptemp.pick view, x, y
	    if @iptemp.valid?
	        changed = @iptemp != @ip
	        @ip.copy! @iptemp
	        view.invalidate if changed
	    end
	end
	
	def onLButtonDown(flags, x, y, view)
		@iptemp.pick view, x, y
		if !@ip1
			if @iptemp.valid?
				@ip1 = Sketchup::InputPoint.new
				@ip1.copy! @iptemp
			end
		else
			if @iptemp.valid?
				@ip2 = Sketchup::InputPoint.new
				@ip2.copy! @iptemp
				execution = ["0: Reprecussion (Other workpieces)",
	    					 "1: Normal"]
				input = UI.inputbox ["diameter","Execution"],
    							[5.mm,execution[1]],
    							["",execution.join("|")],
    							"Hole"
    			if input
    				@diameter = input[0].to_f
	    			cylinder = build_cylinder(@diameter)
	    			bundle = Bundle.open(cylinder)
	    			bundle["type"] = "hole"
	    			bundle["diameter"] = input[0]
	    			if input[1][0,1] == "0"
						bundle["execution"] = "reprecussion"
					else 
						bundle["execution"] = "normal"
					end
	    			bundle.save 
					@ip1 = nil
					@ip2 = nil
				end
			end 
		end
	end
	
	def draw(view) 
		if @ip1
			view.draw_line @ip1.position, @ip.position
		end
		@ip.draw(view)
	end
	
	def get_ArcCurve(vertex)
		curves = vertex.edges.collect{|edge|edge.curve}
		curves.delete_if{|curve| !curve || curve.typename != "ArcCurve"}
		return curves[0]
	end
	
	def build_cylinder(diameter)
		point = @ip1.position
		vector = point.vector_to @ip2.position
		axes = vector.axes
		transformation = Geom::Transformation.axes point, axes[0], axes[1], axes[2]
		group = Sketchup::active_model.active_entities.add_group
		edges = group.entities.add_arc(Geom::Point3d.new(0,0,0),
									   Geom::Vector3d.new(1,0,0),
									   Geom::Vector3d.new(0,0,1),
									   (diameter / 2),
									   0,
									   (Math::PI * 2))
		edges.each{|edge| edge.soft = true}
		face = group.entities.add_face edges
		face.material = [102, 205, 170]
		face.material.alpha = 0.4
		face.back_material = face.material
		face.pushpull -vector.length.to_f
		group.transform! transformation
		return group
	end
end

class GenerateGcodeTool
end

iconPath = File.join(File.dirname(__FILE__), "icons")
File.join(iconPath, "workpiece_l.png")

defineWorkpiece = UI::Command.new("defineWorkpiece") {buildWorkpiece}
defineWorkpiece.small_icon = File.join(iconPath, "workpiece24.png")
defineWorkpiece.large_icon = File.join(iconPath, "workpiece24.png")
defineWorkpiece.tooltip = "Define Workpiece"

defineToolpath = UI::Command.new("defineToolpath") {Sketchup::active_model.select_tool DefineToolpathTool.new}
defineToolpath.small_icon = File.join(iconPath, "toolpath24.png")
defineToolpath.large_icon = File.join(iconPath, "toolpath24.png")
defineToolpath.tooltip = "Define Toolpath"

defineHole = UI::Command.new("defineHole") {Sketchup::active_model.select_tool DefineHoleTool.new}
defineHole.small_icon = File.join(iconPath, "hole24.png")
defineHole.large_icon = File.join(iconPath, "hole24.png")
defineHole.tooltip = "Define Hole"

generateGcode = UI::Command.new("generateGcode") {assemblies = Parser.parse; PostProcessor.make assemblies}
generateGcode.small_icon = File.join(iconPath, "generate24.png")
generateGcode.large_icon = File.join(iconPath, "generate24.png")
generateGcode.tooltip = "Generate CNC files"

toolbar = UI::Toolbar.new "Mini Vistii"
toolbar.add_item defineWorkpiece
toolbar.add_item defineToolpath
toolbar.add_item defineHole if CNC.hasDrills?
toolbar.add_item generateGcode
toolbar.show

puts "UI OK"